﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace UD650_IMG_CSharp
{
    /// <summary>
    /// 声音提示
    /// </summary>
    public static class SoundCode
    {
        public static byte XG_CMD_EXT_CTRL = 0x4B;    //扩展控制
        public static byte FV_V_ASYN = 0;       // 异步
        public static byte FV_V_SYN = 1;       // 同步
        public static byte FV_V_INPUT_FINGE_A = 23;      // 请再放一次
        public static byte FV_V_INPUT_FINGE = 27;      // 请自然轻放手指
        public static byte FV_V_REG_SUCCESS = 0;       // 登记成功
        public static byte FV_V_REG_FAIL = 2;       // 登记失败
        public static byte FV_V_VERIFY_SUCCESS = 33;      // 验证成功	
        public static byte FV_V_VERIFY_FAIL = 32;      // 验证失败
    }


    /// <summary>
    /// 错误枚举
    /// </summary>
    class ErrorCode
    {
        public static int XG_ERR_SUCCESS = 0x00;   //操作成功
        public static int XG_ERR_FAIL = 0x01;  //操作失败
        public static int XG_ERR_COM = 0x02;   //通讯错误
        public static int XG_ERR_DATA = 0x03;   //数据校验错误
        public static int XG_ERR_INVALID_PWD = 0x04;   //密码错误
        public static int XG_ERR_INVALID_PARAM = 0x05;   //参数错误
        public static int XG_ERR_INVALID_ID = 0x06;   //ID错误
        public static int XG_ERR_EMPTY_ID = 0x07;   //指定ID为空（无登录数据）
        public static int XG_ERR_NOT_ENOUGH = 0x08;   //无足够登录空间
        public static int XG_ERR_NO_SAME_FINGER = 0x09;   //不是同一根手指
        public static int XG_ERR_DUPLICATION_ID = 0x0A;   //有相同登录ID
        public static int XG_ERR_TIME_OUT = 0x0B;   //等待手指输入超时
        public static int XG_ERR_VERIFY = 0x0C;   //认证失败
        public static int XG_ERR_NO_NULL_ID = 0x0D;   //已无空ID
        public static int XG_ERR_BREAK_OFF = 0x0E;   //操作中断 
        public static int XG_ERR_NO_CONNECT = 0x0F;   //未连接
        public static int XG_ERR_NO_SUPPORT = 0x10;   //不支持此操作
        public static int XG_ERR_NO_VEIN = 0x11;   //无静脉数据 
        public static int XG_ERR_MEMORY = 0x12;   //内存不足
        public static int XG_ERR_NO_DEV = 0x13;   //设备不存在
        public static int XG_ERR_ADDRESS = 0x14;    //设备地址错误
        public static int XG_INPUT_FINGER = 0x20;   //请求放入手指
        public static int XG_RELEASE_FINGER = 0x21;    //请求拿开手指
    };


    class Program
    {
        /// <summary>
        /// 包数据结构
        /// </summary>
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        public struct XG_PACKET
        {
            public short wPrefix; //包标识0xAABB
            public byte bAddress; //设备地址， 0为广播
            public byte bCmd; //命令码
            public byte bEncode; //数据编码，默认为 0 
            public byte bDataLen; //有效数据长度（字节）
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
            public byte[] bData; //包数据
            public short wCheckSum; //包检验， 0-22字节和
        }


        /// <summary>
        /// 获取版本号
        /// </summary>
        /// int WINAPI XG_GetComApiVer	(	char * 	pVer	)
        /// <param name="pVer">版本号字符串缓存，必须大于16字节</param>
        /// <returns>1.XG_ERR_SUCCESS：获取成功   2.XG_ERR_INVALID_PARAM：参数错误</returns>
        [DllImport("TGXGComAPI.dll", EntryPoint = "TG_GetComApiVer", CallingConvention = CallingConvention.StdCall)]
        public static extern int TG_GetComApiVer(byte[] pVer);

        /// <summary>
        /// 检测是否存在USB静脉模块
        /// </summary>
        /// int WINAPI XG_DetectDev	(	int * 	pUDisk = NULL,int * 	pHid = NULL )
        /// <param name="pUDisk">返回CDROM设备数</param>
        /// <param name="pHid">返回HID设备数</param>
        /// <returns>总的USB设备数</returns>
        [DllImport("TGXGComAPI.dll", EntryPoint = "TG_DetectDev", CallingConvention = CallingConvention.StdCall)]
        public static extern int TG_DetectDev(ref int pUDisk, ref int pHid);


        /// <summary>
        /// 打开设备，如果打开设备成功同时发送XG_CMD_CONNECTION指令
        /// </summary>
        /// int WINAPI XG_ConnectDev	(	UINT8 	Port,UINT8 	Baud,UINT8 	Addr,UINT8 	Password[16],UINT8 	Len,HANDLE 	hHandle = NULL )	
        /// <param name="Port">端口号，0[USB端口]，1-10[COM1-COM10]</param>
        /// <param name="Baud">波特率, 0-4[9600,19200,38400,57600,115200]</param>
        /// <param name="Addr">如Port = 0，此参数用于选择多个USB设备，CDROM驱动优先；如Port>0此参数为设备地址</param>
        /// <param name="Password">输入时为连接密码，连接成功后输出设备名</param>
        /// <param name="Len">密码长度>=8</param>
        /// <returns>1.XG_ERR_SUCCESS:连接成功   2.XG_ERR_FAIL:连接失败</returns>
        [DllImport("TGXGComAPI.dll", EntryPoint = "TG_ConnectDev", CallingConvention = CallingConvention.StdCall)]
        public static extern int TG_ConnectDev(byte Port, byte Baud, byte Addr, byte[] Password, int Len, ref IntPtr hHandle);


        /// <summary>
        /// 发送一个指令包
        /// </summary>
        ///  int WINAPI XG_SendPacket(UINT8 Addr,UINT8 	Cmd,UINT8 Encode,UINT8 	Len,UINT8 * pData,HANDLE Handle = 0 )		
        /// <param name="Addr">设备地址,0[广播，所有设备都接收]，1-255[指定接收设备地址]</param>
        /// <param name="Cmd">指令号</param>
        /// <param name="Encode">数据编码格式</param>
        ///  <param name="Len">数据长度</param>
        /// <param name="pData">包数据</param>
        /// <returns>XG_ERR_SUCCESS:指令包发送成功,XG_ERR_INVALID_PARAM:参数非法,XG_ERR_COM:设备或通信错误</returns>
        [DllImport("TGXGComAPI.dll", EntryPoint = "TG_SendPacket", CallingConvention = CallingConvention.StdCall)]
        public static extern int TG_SendPacket(byte Addr, byte Cmd, byte Encode, byte Len, byte[] pData, IntPtr hHandle);

        /// <summary>
        /// 接收一个指令包
        /// </summary>
        /// int WINAPI XG_RecvPacket(UINT8 Addr,PXG_PACKET pPacket,HANDLE 	Handle = 0 )	
        /// <param name="Addr">设备地址,0[广播，所有设备都接收]，1-255[指定接收设备地址]</param>
        /// <param name="pPacket">接收到的返回包</param>
        /// <returns>XG_ERR_SUCCESS:接收成功,XG_ERR_INVALID_PARAM:参数非法,XG_ERR_COM:设备或通信错误,XG_ERR_DATA:数据校验错误</returns>
        [DllImport("TGXGComAPI.dll", EntryPoint = "TG_RecvPacket", CallingConvention = CallingConvention.StdCall)]
        public static extern int TG_RecvPacket(byte Addr, ref XG_PACKET pPacket, IntPtr hHandle);

        /// <summary>
        /// 检测是否有手指放入，如检测到手指放入返回值大于0
        /// </summary>
        /// int WINAPI	XG_GetFingerStatus(int iAddr, HANDLE Handle);	
        /// <param name="Addr">设备地址,0[广播，所有设备都接收]，1-255[指定接收设备地址]</param>
        /// <param name="Handle">设备句柄</param>
        /// <returns>大于0 检测到手指放入</returns>
        [DllImport("TGXGComAPI.dll", EntryPoint = "TG_GetFingerStatus", CallingConvention = CallingConvention.StdCall)]
        public static extern int TG_GetFingerStatus(int Addr, IntPtr hHandle);


        /// <summary>
        /// 获取图像
        /// </summary>
        /// int WINAPI TG_GetDeviceVeinBmp(HANDLE Handle, UINT8* pEncryptBmp, int* pWidth, int* pHeight, UINT8* pChara, int* pSize);	
        /// <param name="Handle">设备句柄</param>
        /// <param name="pEncryptBmp">数据存放缓冲</param>
        /// <param name="pWidth">图像宽度</param>
        /// <param name="pHeight">图像高度</param>
        /// <param name="pChara">无效</param>
        /// <param name="pSize">无效</param>
        /// <returns>1.XG_ERR_SUCCESS:成功    2.else:失败</returns>
        [DllImport("TGXGComAPI.dll", EntryPoint = "TG_GetDeviceVeinBmp", CallingConvention = CallingConvention.StdCall)]
        public static extern int TG_GetDeviceVeinBmp(IntPtr hHandle, byte[] pEncryptBmp, ref int pWidth, ref int pHeight, byte[] pChara, ref int pSize);

        /// <summary>
        /// 发送XG_CMD_CLOSE_CONNECTION断开连接指令
        /// </summary>
        /// XG_Disconnect(	UINT8 	Addr,HANDLE 	Handle )
        /// <param name="Addr">设备地址,用于485联网时连接设备选择</param>
        /// <param name="Handle"></param>
        /// <returns>1.XG_ERR_SUCCESS:成功    2.XG_ERR_FAIL:失败</returns>
        [DllImport("TGXGComAPI.dll", EntryPoint = "TG_Disconnect", CallingConvention = CallingConvention.StdCall)]
        public static extern int TG_Disconnect(byte Addr, IntPtr hHandle);

        /// <summary>
        /// 发送XG_CMD_CLOSE_CONNECTION指令成功后关闭设备
        /// </summary>
        /// int WINAPI XG_CloseDev(UINT8 	Addr,HANDLE 	Handle = 0);
        /// <param name="Addr">设备地址,0[广播，所有设备都接收]，1-255[指定接收设备地址]</param>
        /// <param name="Handle"></param>
        /// <returns>1.XG_ERR_SUCCESS:关闭成功     2.XG_ERR_FAIL:关闭失败</returns>
        [DllImport("TGXGComAPI.dll", EntryPoint = "TG_CloseDev", CallingConvention = CallingConvention.StdCall)]
        public static extern int TG_CloseDev(byte Addr, IntPtr hHandle);


        /// <summary>
        /// 对二进制数据进行BASE64编码
        /// </summary>
        /// int WINAPI EncodeBase64	(const unsigned char * pSrc,char * pDst,int nSrcLen )	
        /// <param name="pSrc">需要编码的二进制数据</param>
        /// <param name="pDst">BASE64编码后的缓存，缓存大小需要二进制数据的2倍</param>
        /// <param name="nSrcLen">二进制数据的大小</param>
        /// <returns>编码后的字节数</returns>
        [DllImport("TGXGComAPI.dll", EntryPoint = "EncodeBase64", CallingConvention = CallingConvention.StdCall)]
        public static extern int EncodeBase64(byte[] pSrc, byte[] pDst, int nSrcLen);


        // 向设备发出发声指令
        public static int speak(byte Addr, IntPtr hHandle,byte bSound, byte bPlay)
        {
            byte[] buf = new byte[16];
            int i_ret = -1;

            buf[0] = 0x01;   //播放语音
            buf[1] = bSound; //语音序号
            buf[2] = bPlay;  //播放方式，0异步，1同步
            i_ret = Program.TG_SendPacket(Addr, SoundCode.XG_CMD_EXT_CTRL, 0, 3, buf, hHandle);
            if (ErrorCode.XG_ERR_SUCCESS != i_ret)
            {
                return -1;
            }


            XG_PACKET pack = new XG_PACKET();
            i_ret = Program.TG_RecvPacket(Addr, ref pack, hHandle);
            if (ErrorCode.XG_ERR_SUCCESS != i_ret)
            {
                return -1;
            }

            return 0;
        }



        static void Main(string[] args)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
            return;

            
        }
    }
}
